// 格式化 console.log 函数，为了去掉 Vue 中对对象进行 defineProperty 的操作
export function log(...args: any[]) {
  const formatter = new Intl.DateTimeFormat('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });
  const date = new Date();
  console.log(formatter.format(date), ...JSON.parse(JSON.stringify(args)));
}

/**
 * 将十六进制字符串转换为 Uint8Array
 * Each pair of hexadecimal digits is parsed into a single byte.
 *
 * @param hex - The hexadecimal string to be converted.
 * @returns A Uint8Array containing the byte values parsed from the input string.
 */
export const hex2Buffer = (hex: string) => {
  const matches = hex.match(/[\da-f]{2}/gi);
  return matches ? new Uint8Array(matches.map(h => parseInt(h, 16))) : new Uint8Array();
};

export const buffer2String = (buffer: Uint8Array) => {
  const textDecoder = new TextDecoder();
  return textDecoder.decode(buffer);
};

/**
 * 将字符串转换为 Uint8Array，每个字符串的 Unicode 码位转换为一个字节
 *
 * @param dataString - The string to be converted.
 * @returns A Uint8Array containing the byte values parsed from the input string.
 */
export const string2Buffer = (dataString: string) => {
  let data = new Uint8Array(dataString.length);
  for (let i = 0; i < data.length; i++) {
    data[i] = dataString.charCodeAt(i);
  }
  return data;
};

/**
 * 将 Uint8Array 缓冲区转换为十六进制字符串，每个字节转换为两个十六进制表示
 *
 * @param buffer - The Uint8Array buffer to be converted.
 * @returns A string containing the hexadecimal representation of the input buffer.
 */
export const buffer2Hex = (buffer: Uint8Array) => {
  return Array.from(buffer, byte => byte.toString(16).padStart(2, '0'))
    .join('')
    .toUpperCase();
};

/**
 * 处理 Unicode 转义序列（如 "\uXXXX"）
 */
export const unicodeEscapeToString = (unicodeStr: string) => {
  return unicodeStr
    .replace(/\\u[\dA-F]{4}/gi, match => String.fromCharCode(parseInt(match.replace(/\\u/g, ''), 16)))
    .replace(/\0/g, '');
};

/**
 * 将十六进制字符串转换为字符串
 */
export const hex2String = (hex: string) => {
  // 检查是否全零
  if (/^0+$/.test(hex.replace(/^0x|\s/g, ''))) {
    return ''; // 直接返回原始十六进制表示
  }
  const string = hex.replace(/../g, function (match) {
    return String.fromCharCode(parseInt(match, 16));
  });
  // 去掉尾部多余的 \0
  return string.replace(/\0/g, '');
};

/**
 * 将一个十六进制字符串（可选带符号的 32bit IEEE754 浮点数）转换为一个浮点数字符串
 * @param {string | number | undefined} t - 需要转换的十六进制字符串
 * @param {boolean} [type=true] - 是否需要转换为浮点数，如果为 false，将原样返回
 * @returns {string} - 转换后的浮点数字符串
 */
export const hex2Single = (t: string | number | undefined, type = true) => {
  if (t === undefined) return '';
  if (typeof t === 'number') t = t.toString();
  t = t.replace(/\s+/g, '');
  if (t == '') {
    return '';
  }
  if (t == '00000000') {
    return '0';
  }
  if (isAllF(t)) {
    return '';
  }
  if (t.length > 8 || isNaN(parseInt(t, 16))) {
    return 'Error';
  }
  if (t.length < 8) {
    t = fillString(t, '0', 8, true);
  }
  t = parseInt(t, 16).toString(2);
  t = fillString(t, '0', 32, true);
  const s = t.substring(0, 1);
  let m = t.substring(9);
  const e = parseInt(t.substring(1, 9), 2) - 127;
  m = '1' + m;
  if (e >= 0) {
    m = m.substring(0, e + 1) + '.' + m.substring(e + 1);
  } else {
    m = '0.' + fillString(m, '0', m.length - e - 1, true);
  }
  if (m.indexOf('.') == -1) {
    m = m + '.0';
  }
  var a = m.split('.');
  var mi = parseInt(a[0], 2);
  var mf = 0;
  for (var i = 0; i < a[1].length; i++) {
    mf += parseFloat(a[1].charAt(i)) * Math.pow(2, -(i + 1));
  }
  let m2 = mi + mf;
  if (Number(s) === 1) {
    m2 = 0 - m2;
  }
  return type ? m2 : m2.toString().substring(0, m2.toString().indexOf('.') + 4);
};

/**
 * 将十六进制字符串或数字转换为整数
 *
 * @param {string | number | undefined} t - The hexadecimal value to be converted.
 * @returns {number | string} The integer representation of the hexadecimal input, or an empty string if input is undefined.
 */

export const hex2Int = (t: string | number | undefined) => {
  if (t === undefined) return '';
  if (isAllF(String(t))) return '';
  if (typeof t === 'number') t = t.toString();
  return parseInt(t, 16);
};

/**
 * 填充字符串直到达到指定长度
 *
 * @param {string} t - The string to fill.
 * @param {string} c - The character to fill with.
 * @param {number} n - The desired length of the resulting string.
 * @param {boolean} b - Whether to fill from the beginning (true) or end (false).
 * @returns {string} The filled string.
 */
export const fillString = (t: string, c: string, n: number, b: boolean) => {
  if (t == '' || c.length != 1 || n <= t.length) {
    return t;
  }
  var l = t.length;
  for (var i = 0; i < n - l; i++) {
    if (b == true) {
      t = c + t;
    } else {
      t += c;
    }
  }
  return t;
};

/**
 * Calculate the CRC-16 checksum of a given hexadecimal string.
 * The CRC-16 checksum is calculated using the polynomial x^16 + x^15 + x^2 + 1.
 * The input string should be a hexadecimal string, and the output will be a 4-character
 * hexadecimal string representing the checksum.
 * @param {string} dataHex - The input hexadecimal string.
 * @returns {string} The CRC-16 checksum as a 4-character hexadecimal string.
 */
export const crc16 = (dataHex: string) => {
  const dataBytes = [];
  for (let i = 0; i < dataHex.length; i += 2) {
    dataBytes.push(parseInt(dataHex.substring(i, i + 2), 16));
  }
  let crc = 0xffff;
  const polynomial = 0xa001; // This is the polynomial x^16 + x^15 + x^2 + 1
  for (const byte of dataBytes) {
    crc ^= byte;
    for (let i = 0; i < 8; i++) {
      if (crc & 0x0001) {
        crc = ((crc >> 1) ^ polynomial) & 0xffff;
      } else {
        crc >>= 1;
      }
    }
  }
  const res = crc.toString(16).toUpperCase().padStart(4, '0');
  return convertEndian(res);
};

/**
 * 初始化 CRC32 查找表
 */
function initCrc32Tab() {
  const crcTab32 = new Uint32Array(256);
  for (let i = 0; i < 256; i++) {
    let crc = i;

    for (let j = 0; j < 8; j++) {
      if (crc & 0x00000001) {
        crc = (crc >>> 1) ^ 0xedb88320;
      } else {
        crc = crc >>> 1;
      }
    }
    crcTab32[i] = crc;
  }
  return crcTab32;
}

/**
 * 计算字节数组的 CRC32 值
 * @param {string} hexString - 输入的字符串
 * @returns {number} CRC32 值
 */
export function crc32(hexString: string) {
  const inputBytes = hex2Buffer(hexString);
  if (!inputBytes || inputBytes.length === 0) {
    return '';
  }

  const crcTab32 = initCrc32Tab();

  let crc = 0xffffffff;

  for (let i = 0; i < inputBytes.length; i++) {
    const longC = 0x000000ff & inputBytes[i];
    const tmp = crc ^ longC;
    crc = (crc >>> 8) ^ crcTab32[tmp & 0xff];
  }

  const res = (crc ^ 0xffffffff) >>> 0; // >>> 0 确保结果为无符号32位整数
  return res.toString(16).padStart(8, '0');
}

/**
 * 大小端序转换
 */
export const convertEndian = (hexData: string) => {
  const matched = hexData.match(/.{1,2}/g);
  if (!matched) return '';
  return matched.reverse().join('');
};

/**
 * 检查字符串是否全为 F，忽略大小写
 */
function isAllF(str: string): boolean {
  return /^f+$/i.test(str);
}

export const isDevelopment = () => {
  return runType === 'dev' || runType === 'app-dev';
};

export const isEmpty = (value: any): boolean => {
  return ['', undefined, null, false].includes(value)
}
